package com.heima.comment.service.impl;
import java.util.Date;

import com.heima.article.feign.ApArticleFeign;
import com.heima.comment.service.ApCommentService;
import com.heima.common.contants.MQConstants;
import com.heima.common.contants.RedisConstants;
import com.heima.common.dtos.AppHttpCodeEnum;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.exception.LeadNewsException;
import com.heima.model.article.dtos.UpdateArticleMsg;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentRepayLikeDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.user.pojos.ApUser;
import com.heima.user.feign.ApUserFeign;
import com.heima.utils.common.BeanHelper;
import com.heima.utils.common.JsonUtils;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.common.ThreadLocalUtils;
import com.heima.wemedia.feign.WemediaFeign;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;


@Service
public class ApCommentServiceImpl implements ApCommentService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ApArticleFeign articleFeign;
    @Autowired
    private ApUserFeign userFeign;
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;
    @Override
    public ResponseResult saveComment(CommentDto commentDto) {
        try {
            /**
             * - 在文章详情中发表评论，输入内容发表评论
             * - 必须登录后才能发表评论
             * - 评论内容不能超过140字
             * - 评论内容需要做文本垃圾检测
             */

            //参数校验
            if (commentDto == null || commentDto.getContent() == null || commentDto.getArticleId() == null){
                throw new LeadNewsException(AppHttpCodeEnum.PARAM_REQUIRE);
            }

            //必须登录后才能发表评论
            ApUser user = (ApUser) ThreadLocalUtils.get();
            if (user == null){
                throw new LeadNewsException(AppHttpCodeEnum.NEED_LOGIN);
            }

            //根据文章id查询是否可以评论
            Boolean isComment = articleFeign.isComment(commentDto.getArticleId());
            if (!isComment){
                return ResponseResult.okResult(200,"当前文章作者设置为不可评论");
            }

            //评论内容不能超过140字
            if (commentDto.getContent().length()>140){
                throw new LeadNewsException(400,"评论内容不能超过140字");
            }

            //评论内容需要做文本垃圾检测
            boolean flag = handleSensitiveScan(commentDto.getContent());
            if (!flag){
                //违规词
                return ResponseResult.errorResult(400,"评论含有违规词");
            }

            user = userFeign.findById(user.getId()).getData();
            //插入数据
            ApComment apComment = new ApComment();

            apComment.setAuthorId(user.getId());
            apComment.setAuthorName(user.getName());
            apComment.setEntryId(commentDto.getArticleId());
            apComment.setTYPE((short)0);
            apComment.setContent(commentDto.getContent());

            apComment.setLikes(0);
            apComment.setReply(0);
            apComment.setFlag((short)0);
            apComment.setOrd(0);
            apComment.setCreatedTime(new Date());
            apComment.setUpdatedTime(new Date());
            apComment.setStatus(true);

//            apComment.setOperation((short) 1);
            ApComment save = mongoTemplate.save(apComment);

//            String key = RedisConstants.COMMENT_LIKE + save.getId() + user.getId();
//            redisTemplate.delete(key);

            // kafka同步  发送消息给KafkaStream进行数据同步
            UpdateArticleMsg articleMsg = new UpdateArticleMsg();
            articleMsg.setArticleId(commentDto.getArticleId());
            articleMsg.setType(UpdateArticleMsg.UpdateArticleType.COMMENT);

            kafkaTemplate.send(MQConstants.HOT_ARTICLE_INPUT_TOPIC,JsonUtils.toString(articleMsg));
            return ResponseResult.okResult(null);
        } finally {
            ThreadLocalUtils.remove();
        }
    }



    /**
     * 自定义敏感词检测
     *
     */
    public boolean handleSensitiveScan(String content) {
        boolean flag = true;
        //查询自定义敏感词列表//可以优化：第一次查询数据库，第n次查询redis
        //先从Redis查询违规词
        List<String> wordList = null;
        String sensitives = redisTemplate.opsForValue().get(RedisConstants.SENSITIVES);

        if (StringUtils.isNotEmpty(sensitives)){
            wordList = JsonUtils.toList(sensitives, String.class);
        }

        if (wordList == null){
            //去数据库查
            wordList = wemediaFeign.findAllAndRedis().getData();
        }
        //使用DFA算法构建词库

        SensitiveWordUtil.initMap(wordList);

        //使用DFA词库匹配文章内容
        //准备匹配的内容

        Map<String, Integer> result = SensitiveWordUtil.matchWords(content);

        //根据结果进行处理文章状态
        if(result!=null && result.size()>0){
            flag = false;

        }
        return flag;
    }

    //查询评论列表
    @Override
    public ResponseResult<List<ApComment>> load(CommentDto commentDto) {
        try {
            //校验参数
            if (commentDto == null || commentDto.getArticleId()== null
                    ||commentDto.getMinDate() == null || commentDto.getIndex() == null){
                throw new LeadNewsException(AppHttpCodeEnum.PARAM_REQUIRE);
            }
            //构造查询条件
            Query query = Query.query(Criteria.where("entryId").is(commentDto.getArticleId())
                    .and("createdTime").lt(commentDto.getMinDate()));

            query.with(Sort.by(Sort.Direction.DESC,"createdTime"));

            List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);



            //判断是否登录
            ApUser user = (ApUser) ThreadLocalUtils.get();
            if ( user!=null){
                //遍历评论是否点赞
                if (!CollectionUtils.isEmpty(commentList)){
                    for (ApComment comment : commentList) {

                        String key = RedisConstants.COMMENT_LIKE + comment.getId() + user.getId();
                        String like = redisTemplate.opsForValue().get(key);

                        //点赞
                        if (StringUtils.isNotEmpty(like)){
                            comment.setOperation((short) 0);
                        }else {
                            comment.setOperation((short) 1);
                        }
                    }
                }
            }
            

            if (commentList != null){
                return ResponseResult.okResult(commentList);
            }
            return ResponseResult.okResult(null);
        } finally {

        }
    }

    //文章评论点赞和取消
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        try {
            //校验参数
            if (dto.getCommentId() == null){
                throw new LeadNewsException(AppHttpCodeEnum.PARAM_REQUIRE);
            }

            //判断登录
            ApUser user = (ApUser) ThreadLocalUtils.get();
            if (user == null){
                throw new LeadNewsException(AppHttpCodeEnum.NEED_LOGIN);
            }

            //判断是点赞还是取消点赞
            //修改文章评论点赞数量
            if (dto.getOperation() == 0){
                //点赞
                //判断是否已经点赞
                //从Redis查询是否点赞
                String key = RedisConstants.COMMENT_LIKE + dto.getCommentId() + user.getId();
                String commentLike = redisTemplate.opsForValue().get(key);
                if (StringUtils.isNotEmpty(commentLike)){
                    return ResponseResult.okResult(200,"你已经点赞，无需再点赞");
                }

                //未点赞 添加Redis 修改评论表点赞数量
                redisTemplate.opsForValue().set(key,dto.getCommentId());

                Query query = Query.query(Criteria.where("_id").is(dto.getCommentId()));
                ApComment comment = mongoTemplate.findOne(query, ApComment.class);
                comment.setLikes(comment.getLikes()+1);

                mongoTemplate.save(comment);
                return ResponseResult.okResult(88);
            }else {
                //取消点赞
                //判断是否已经点赞
                String key = RedisConstants.COMMENT_LIKE + dto.getCommentId() + user.getId();
                String commentLike = redisTemplate.opsForValue().get(key);
                if (StringUtils.isEmpty(commentLike)){
                    return ResponseResult.okResult(200,"你未点赞，无需取消点赞");
                }
                //取消点赞 从Redis删除数据 修改评论表点赞数量
                redisTemplate.delete(key);

                Query query = Query.query(Criteria.where("_id").is(dto.getCommentId()));
                ApComment comment = mongoTemplate.findOne(query, ApComment.class);
                comment.setLikes(comment.getLikes()-1);

                mongoTemplate.save(comment);
                return ResponseResult.okResult(88);
            }




        } finally {
            ThreadLocalUtils.remove();
        }
    }
}
